import type { RuleObject } from "antd/lib/form";
import type { CSSProperties } from "react";
import type { RowProps } from "antd";
import type { FormItem } from "./formItem";
import type { ColEx, ComponentType } from "./index";
// import type { ButtonProps as AntdButtonProps } from "@/components/Button";
import type { ButtonProps as AntdButtonProps } from "antd/lib/button/index";
import type { TableActionType } from "@/components/Table/types/table";
import { FormInstance } from "antd";

export type FieldMapToTime = [string, [string, string], (string | [string, string])?][];

export type Rule = RuleObject & {
	trigger?: "blur" | "change" | ["change", "blur"];
};

export interface RenderCallbackParams {
	schema: FormSchemaInner;
	values: Recordable;
	field: string;
}

export interface ButtonProps extends AntdButtonProps {
	text?: string;
}

export interface FormActionType extends FormInstance {
	// yudao
	updateSchema: (data: Partial<FormSchemaInner> | Partial<FormSchemaInner>[]) => void;
	resetSchema: (data: Partial<FormSchemaInner> | Partial<FormSchemaInner>[]) => void;
	setProps: (formProps: Partial<FormProps>) => void;
	handleSubmit: () => Promise<void>;
}

export type RegisterFn = (formInstance: FormActionType) => void;

export type UseFormReturnType = [RegisterFn, FormActionType];

export interface FormProps {
	name?: string;
	layout?: "vertical" | "inline" | "horizontal";
	// Form value
	model?: Recordable;
	// The width of all items in the entire form
	labelWidth?: number | string;
	// alignment
	labelAlign?: "left" | "right";
	// Row configuration for the entire form
	rowProps?: RowProps;
	// Submit form on reset
	submitOnReset?: boolean;
	// Submit form on form changing
	submitOnChange?: boolean;
	// Col configuration for the entire form
	labelCol?: Partial<ColEx>;
	// Col configuration for the entire form
	wrapperCol?: Partial<ColEx>;

	// General row style
	baseRowStyle?: CSSProperties;

	// General col configuration
	baseColProps?: Partial<ColEx>;

	// Form configuration rules
	schemas?: FormSchema[];
	// Function values used to merge into dynamic control form items
	mergeDynamicData?: Recordable;
	// Compact mode for search forms
	compact?: boolean;
	// Blank line span
	emptySpan?: number | Partial<ColEx>;
	// Internal component size of the form
	size?: "default" | "small" | "large";
	// Whether to disable
	disabled?: boolean;
	// Time interval fields are mapped into multiple
	fieldMapToTime?: FieldMapToTime;
	// Placeholder is set automatically
	autoSetPlaceHolder?: boolean;
	// Auto submit on press enter on input
	autoSubmitOnEnter?: boolean;
	// Check whether the information is added to the label
	rulesMessageJoinLabel?: boolean;
	// Whether to show collapse and expand buttons
	showAdvancedButton?: boolean;
	// Whether to focus on the first input box, only works when the first form item is input
	autoFocusFirstItem?: boolean;
	// Automatically collapse over the specified number of rows
	autoAdvancedLine?: number;
	// Always show lines
	alwaysShowLines?: number;
	// Whether to show the operation button
	showActionButtonGroup?: boolean;

	// Reset button configuration
	resetButtonOptions?: Partial<ButtonProps>;

	// Confirm button configuration
	submitButtonOptions?: Partial<ButtonProps>;

	// Operation column configuration
	actionColOptions?: Partial<ColEx>;

	// Show reset button
	showResetButton?: boolean;
	// Show confirmation button
	showSubmitButton?: boolean;

	resetFunc?: () => Promise<void>;
	submitFunc?: () => Promise<void>;
	transformDateFunc?: (date: any) => string;
	colon?: boolean;

	// 表单默认值
	initialValues: Recordable;
}

export interface RenderOpts {
	disabled: boolean;
	[key: string]: any;
}

interface BaseFormSchema {
	// Field name
	field: string;
	// Extra Fields name[]
	fields?: string[];
	// Event name triggered by internal value change, default change
	changeEvent?: string;
	// Variable name bound to v-model Default value
	valueField?: string;
	// Label name
	label?: string | JSX.Element;
	// Auxiliary text
	subLabel?: string;
	// Help text on the right side of the text
	helpMessage?: string | string[] | ((renderCallbackParams: RenderCallbackParams) => string | string[]);
	// BaseHelp component props
	helpComponentProps?: Partial<HelpComponentProps>;
	// Label width, if it is passed, the labelCol and WrapperCol configured by itemProps will be invalid
	labelWidth?: string | number;
	// Disable the adjustment of labelWidth with global settings of formModel, and manually set labelCol and wrapperCol by yourself
	disabledLabelWidth?: boolean;
	// Component parameters
	componentProps?:
		| ((opt: {
				schema: FormSchema;
				tableAction: TableActionType;
				formActionType: FormActionType;
				formModel: Recordable;
		  }) => Recordable)
		| object;
	// Required
	required?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);

	suffix?: string | number | ((values: RenderCallbackParams) => string | number);

	// Validation rules
	rules?: Rule[];
	// Check whether the information is added to the label
	rulesMessageJoinLabel?: boolean;

	// Reference formModelItem
	itemProps?: Partial<FormItem>;

	// col configuration outside formModelItem
	colProps?: Partial<ColEx>;

	// 默认值
	defaultValue?: any;

	// 额外默认值数组对象
	defaultValueObj?: { [key: string]: any };

	// 是否自动处理与时间相关组件的默认值
	isHandleDateDefaultValue?: boolean;

	isAdvanced?: boolean;

	// Matching details components
	span?: number;

	ifShow?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);

	show?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);

	// Render the content in the form-item tag
	render?: (renderCallbackParams: RenderCallbackParams, opts: RenderOpts) => JSX.Element | JSX.Element[] | string;

	// Rendering col content requires outer wrapper form-item
	renderColContent?: (renderCallbackParams: RenderCallbackParams, opts: RenderOpts) => JSX.Element | JSX.Element[] | string;

	renderComponentContent?:
		| ((renderCallbackParams: RenderCallbackParams, opts: RenderOpts) => any)
		| JSX.Element
		| JSX.Element[]
		| string;

	// Custom slot, similar to renderColContent
	colSlot?: string;

	dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);

	dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[];
}
export interface ComponentFormSchema extends BaseFormSchema {
	// render component
	component: ComponentType;
}

export interface SlotFormSchema extends BaseFormSchema {
	// Custom slot, in from-item
	slot: string;
}

export type FormSchema = ComponentFormSchema | SlotFormSchema;

export type FormSchemaInner = Partial<ComponentFormSchema> & Partial<SlotFormSchema> & BaseFormSchema;

export function isSlotFormSchema(schema: FormSchemaInner): schema is SlotFormSchema {
	return "slot" in schema;
}

export function isComponentFormSchema(schema: FormSchemaInner): schema is ComponentFormSchema {
	return !isSlotFormSchema(schema);
}

export interface HelpComponentProps {
	maxWidth: string;
	// Whether to display the serial number
	showIndex: boolean;
	// Text list
	text: any;
	// colour
	color: string;
	// font size
	fontSize: string;
	icon: string;
	absolute: boolean;
	// Positioning
	position: any;
}

export interface AdvanceState {
	isAdvanced: boolean;
	hideAdvanceBtn: boolean;
	isLoad: boolean;
	actionSpan: number;
}
